// PGLScript.h: interface for the CPGLScript class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_PGLSCRIPT_H__701CD044_1B61_438F_B452_C688947E212C__INCLUDED_)
#define AFX_PGLSCRIPT_H__701CD044_1B61_438F_B452_C688947E212C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <boost/utility.hpp>

class CPGLDialog;
class CPGLDialogList;

/*! 
	\defgroup ScriptGroup Scriting and external interfaces
	\ingroup PGLMFC
*/


/*! \brief A Scripting front end.

  \ingroup ScriptGroup
*/
#ifdef _PGLMFC_DLL
#define PGLMFC_EXT_CLASS _declspec(dllexport)
#else
#define PGLMFC_EXT_CLASS _declspec(dllimport)
#endif

class PGLMFC_EXT_CLASS CPGLScript :
	public boost::noncopyable
{
public:
	//! region container
	typedef std::map< long, CPGLRegionPtr > RegionPtrContainer;

	//! \name Constructor
	//@{
	//! Default constructor
	CPGLScript();
	~CPGLScript();
	//@}


	//! \name Region and dialogs handling
	//@{
	/*! \brief Create a dialog and a PGL region
	\return the region ID if successful, 0 otherwise
	*/
	long Figure();
	/*! \brief Create a region (whitout dialog)
	\return the region ID if successful, 0 otherwise
	*/
	long Region();
	//! return current region
	long GetCR() const	{	return m_dwCurRegionID;};
	//! sets the current region
	bool SetCR( long dwRegionID);
	//! Get the current dialog ID
	long GetCD() const	{	return m_dwCurDlgID;};
	/*! \brief Opens a modal dialog with region

	\param lRegionID ID of the region to show
	\param dwFlags Combination of #CPGLDialog::EOption enumeration, default is 0

	\sa CPGLDialog::EOption
	*/
	int DoModalRegion( long lRegionID, DWORD dwFlags = 0 );
	//! Close a figure
	void CloseFigure( long lFigureID);
	//! Close all dialog windows
	void CloseAllFigures();
	//! Destroys the region
	void CloseRegion( long lFigureID );
	//! Close all stand alone regions
	void CloseAllRegions();

	//! \name Subplotting
	//@{
	/*! \brief Subploting method

	\param lRegionID ID of the parent region, if 0 the current region is used,
	\param nRows number of rows, must be >= 1
	\param nCols number of columns, must be >= 1
	*/
	long Divide(long lRegionID, size_t nRows, size_t nCols);

	/*! \brief Create a subplotting layout
	
	\param lRegionID ID of the parent region, if 0 the current region is used,
	\param szLayout xml string describing the layout
	
	  \sa CPGLRegion::Divide
	*/
	long Layout(long lRegionID, LPCTSTR szLayout);

	//! returns the uIndex object in the region, 0 if the object is not inside that region
	long GetObject( long lRegionID, size_t uIndex );

	//! returns the number of objects
	long GetObjectsSize( long lRegionID);

	//! removes the i-th object
	void RemoveObject( long lRegionID, size_t uIndex );

	//! returns the uIndex child of the region, 0 if invalid index
	long GetChild( long lRegionID, size_t uIndex );

	//! returns the number of childrens
	long GetChildrenSize( long lRegionID );

	//! removes the i-th child
	void RemoveChild( long lRegionID, size_t uIndex );

	//! returns the parent of the object, 0 if failed or no parent
	long GetParent(long uID );

	//! Move current region to parent and returns current region ID
	long OutOfChild();
	//@}

	//! \name 1D Charts
	//@{
	/*! \brief plot y versus x

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param pX x vector
	\param pY y vector
	\param szFlags line appearance flags

	If no region have been created yet, a new Figure is allocated.
	*/
	long Plot(
		long lRegionID, 
		CPGLDataPtr pX, 
		CPGLDataPtr pY, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief plot y lenarly versus x

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param dX0 initial x
	\param dXStep x step
	\param pY y vector
	\param szFlags line appearance flags

	If no region have been created yet, a new Figure is allocated.
	*/
	long PlotY(
		long lRegionID, 
		float fX0, 
		float fXStep, 
		CPGLDataPtr pY, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief plot y versus x with level of detail

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param pX x vector
	\param pY y vector
	\param szFlags line appearance flags


	If no region have been created yet, a new Figure is allocated.
	*/
	long PlotLOD(
		long lRegionID, 
		CPGLDataPtr pX, 
		CPGLDataPtr pY, 
		float fCompressionRatio, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief plot y linearly versus x with level of detail

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param dX0 initial x
	\param dXStep x step
	\param pY y vector
	\param szFlags line appearance flags


	If no region have been created yet, a new Figure is allocated.
	*/
	long PlotLODY(
		long lRegionID, 
		float fX0, 
		float fXStep, 
		CPGLDataPtr pY, 
		float fCompressionRatio, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief plots the function szFcnX versus x

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param pX x vector
	\param szFcnX a mathematical expression whose only variable is x
	\param szFlags line appearance flags

	If no region have been created yet, a new Figure is allocated.
	*/
	long PlotFcn(
		long lRegionID, 
		CPGLDataPtr pX, 
		LPCTSTR szFcnX = _T("x"), 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief plot y versus x

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param pX x vector
	\param szFcnX a mathematical expression whose only variable is x
	\param szFlags line appearance flags

	If no region have been created yet, a new Figure is allocated.
	*/
	long PlotFcnY(
		long lRegionID, 
		long nSteps, 
		float fX0, 
		float fXStep, 
		LPCTSTR szFcnX = _T("x"), 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief Draws an horizontal line
	
	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param fY vertical coordinate of the line
	\param szFlags format string.
	*/
	long PlotHor(
		long lRegionID, 
		float fY, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief Draws a vertical line
	
	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param fX horizontal coordinate of the line
	\param szFlags format string.
	*/
	long PlotVer(
		long lRegionID, 
		float fX, 
		LPCTSTR szFlags = _T("")
		);
	//@}

	//! \name 2D Charts
	//@{
	//! Creates on fixed step lattice
	long FixedStepMap(long lRegionID, long nXSteps, float fX0, float fXStep, long nYSteps, float fY0, float fYStep, CPGLDataPtr pValues, LPCTSTR szFlags);
	//! Creates a map based on a regular latice
	long RegularMap(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, CPGLDataPtr pValues, LPCTSTR szFlags);
	//! Creates a vector field based on fixed step lattice
	long FixedStepVectorField(long lRegionID, long nXSteps, float fX0, float fXStep, long nYSteps, float fY0, float fYStep, CPGLDataPtr pVx, CPGLDataPtr pVy, LPCTSTR szFlags);
	//! Creates a vector field based on a regular
	long RegularVectorField(long lRegionID, CPGLDataPtr pX, CPGLDataPtr pY, CPGLDataPtr pVx, CPGLDataPtr pVy, LPCTSTR szFlags);
	//@}

	//! \name Miscellanous charts
	//@{
	/*! \brief Plot histogram

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param pY y vector
	\param szFlags line appearance flags


	If no region have been created yet, a new Figure is allocated.
	*/
	long Histogram(
		long lRegionID, 
		CPGLDataPtr pY, 
		LPCTSTR szFlags = _T("")
		);

	/*! \brief Draw error bars

	If no region have been created yet, a new Figure is allocated.
	*/
	long ErrorBar(
		long lRegionID, 
		CPGLDataPtr pX, 
		CPGLDataPtr pY, 
		CPGLDataPtr pErrorUp, 
		CPGLDataPtr pErrorDown, 
		LPCTSTR szFlags
		);

	/*! \brief Draw error bars with linearly space x coordinates

	If no region have been created yet, a new Figure is allocated.
	*/
	long ErrorBarY(
		long lRegionID, 
		float fX0, 
		float fXStep, 
		CPGLDataPtr pY, 
		CPGLDataPtr pErrorUp, 
		CPGLDataPtr pErrorDown,
		LPCTSTR szFlags
		);

	/*! \brief Draw scatter


	If no region have been created yet, a new Figure is allocated.
	*/
	long Scatter(
		long lRegionID, 
		CPGLDataPtr pX, 
		CPGLDataPtr pY, 
		CPGLDataPtr pValues, 
		LPCTSTR szFlags
		);

	/*! \brief Stock chart (Open, high, low, close)

	If no region have been created yet, a new Figure is allocated.
	*/
	long Stock(
		long lRegionID, 
		float fX0, 
		float fXStep, 
		CPGLDataPtr pOpen, 
		CPGLDataPtr pHigh, 
		CPGLDataPtr pLow, 
		CPGLDataPtr pClose, 
		LPCTSTR szFlags
		);

	/*! \brief CandleStick chart (Open, high, low, close)

	If no region have been created yet, a new Figure is allocated.
	*/
	long CandleStick(
		long lRegionID, 
		float fX0, 
		float fXStep, 
		CPGLDataPtr pOpen, 
		CPGLDataPtr pHigh, 
		CPGLDataPtr pLow, 
		CPGLDataPtr pClose, 
		LPCTSTR szFlags
		);
	/*! \brief Draws an image from file

	\param lRegionID current region ID, if 0 or non valid, current region is used,
	\param szFileName image file name. Supported extensions are: png, jpeg, tiff, bmp, emf, wmf, 
	\param szFlags format parameters
	*/
	long Image(
		long lRegionID, 
		LPCTSTR szFileName, 
		LPCTSTR szFlags = _T("")
		);
	//@}

	//! \name Modifying the region appearance
	//@{
	//! Sets the left label
	long LeftLabel(
		long lRegionID, 
		LPCTSTR szLabel
		);
	//! Sets the bottom label
	long BottomLabel(
		long lRegionID, 
		LPCTSTR szLabel
		);
	//! Sets the bottom label
	long Title(
		long lRegionID, 
		LPCTSTR szLabel
		);
	//! Sets the bottom label
	long RightLabel(
		long lRegionID, 
		LPCTSTR szLabel
		);

	/*! \brief Adds a legend to the region
	
	\param lRegionID ID of the region
	*/
	long Legend(
		long lRegionID
		);
	/*!
	
	  \param lRegionID ID of the region
	  \param szState on, off, xon, xoff, yon, yoff
	\return returns the grid ID (if xon, xoff, x grid and yon, yoff y grid, otherwise 0)
	  Turn the grid lines on or off
	*/
	long Grid(
		long lRegionID, 
		LPCTSTR szState
		);
	//@}

	//! \name Zooming
	//@{
	/*! \brief Zoom all

	\param lRegionID ID of the region
	\param bRecurse true if zoom all is applied to the child regions
	*/
	void ZoomAll(
		long lRegionID, 
		bool bRecurse = true
		);
	/*! \brief Zoom a region

	\param lRegionID ID of the region
	\param rect rectangle to zoom on
	*/
	void Zoom(
		long lRegionID, 
		CPGLRectD rect
		);

	/*! gets the range of the region

  \param lRegionID ID of the region
  \param rect rectangle structure filled with the region range
  \return true if succesful, false otherwize
	*/
	bool GetZoom(
		long lRegionID, 
		CPGLRectD& rect
		);
	//! Sets autoscale on-off
	void AutoZoom(
		LPCTSTR szState 
		);
	//@}

	//! \name Property setters and getters
	//@{
	//! Set function
	void Set(long uObjectID, LPCTSTR szPropAndValues);
	//! Get function
	void Get(long uObjectID, LPCTSTR szProp, CString& sValue);
	//! returns help about the object
	void GetHelp( long uID, CString& str);
	//@}

	//! \name Serialization and file output
	//@{
	/*! \brief load from xml

	\param lRegionID ID of the region to load, if 0, current region is used
	\param szFileName name of the file to load
	*/
	long LoadFromXML(long lRegionID, LPCTSTR szFileName );

	/*! \brief save to xml

	\param lRegionID region to save
	\param szFileName file name
	\param bZipping zipping on / off
	*/
	bool SaveToXML(long lRegionID, LPCTSTR szFileName, bool bZipping= false );

	/*! \brief Loads a comma separated file
	
	\param lRegionID region to add the line
	\param szFileName file to load
	\return true if succesfule
	*/
	bool LoadCSVFile( long lRegionID, LPCTSTR szFileName);	

	/*! render to file

	\param lRegionID ID of the region to render, if O current is used
	\param szFileName file name
	\param szFormat output file format string

	\par File type
	type=[file type]
	The available file types are :
		- jpeg or jpg
		- bmp, Windows bitmap
		- png, PNG
		- tiff, TIFF
		- emf, Extented Metafile compatible with GDI only
		- emfp, Extented Metafile compatible with GDI+ only
		- emfpd,  Extented Metafile compatible with GDI and GDI+
		- eps, Encapsulated Postscript
		- svg, Scalable Vector Graphic
		- svgz, Zipped Scalable Vector Graphic
	\par Dimension
	dim=width x height

	\par Quality (for JPEG rendering)
	quality= [1..100]

	\sa CPGLArchive::EFileFormat
	*/
	bool RenderToFile(
		long lRegionID, 
		LPCTSTR szFileName, 
        LPCTSTR szFormat 
		);

	/*! Render to IStream storage

	\param lRegionID ID of the region to render, if O current is used
	\param pStream stream opened for writing
	\param szFormat output file format string

	\par File type
	type=[file type]
	The available file types are :
		- jpeg or jpg
		- bmp, Windows bitmap
		- png, PNG
		- tiff, TIFF
		- emf, Extented Metafile compatible with GDI only
		- emfp, Extented Metafile compatible with GDI+ only
		- emfpd,  Extented Metafile compatible with GDI and GDI+
	\par Dimension
	dim=width x height

	\par Quality (for JPEG rendering)
	quality= [1..100]

	\sa CPGLArchive::EFileFormat
	*/
	bool RenderToStream(
		long uRegion, 
		IStream* pStream, 
		LPCTSTR szFormat
		);

	/*! \brief Render to GDI+ Image

	\param lRegionID region to render
	\param pImage valid GDI+ image pointer
	*/
	bool RenderToImage(
		long lRegionID, 
		Gdiplus::Image* pImage,
        LPCTSTR szFlags = _T("")
		);

    /*! \brief renders to a memory bitmap
    
    \param lRegionID region to render
    \param width_ width in pixels of the bitmap buffer
    \param height_ width in pixels of the bitmap buffer
    \param stride_ bitmap buffer stride
    \param bpp_ byte per pixels
    \param bits_ bitmap buffer
    */
	bool RenderToBitmap(
		long lRegionID,
		unsigned int width_,
		unsigned int height_,
		unsigned int stride_,
		unsigned int bpp_,
		void* bits_,
        LPCTSTR szFlags = _T("")
        );
	
	//@}

protected:
	//! Get Current dialog
	CPGLDialog* GetCurrentDialog();
	//! return a non-safe pointer to a region
	CPGLRegionStPtr GetRegion(long lRegionID);
	//! returns a non-safe smart pointer to a reigon
	CPGLRegionPtr GetRegionPtr(long lRegionID);
	//! return a safe pointer to a region
	CPGLRegionStPtr GetSafeRegion(long lRegionID);

	void Update(CPGLRegionStPtr pRegion, bool bZoomAll);
	//! \name Format methods
	//@{
	void ParseObjectFormat( CPGLObjectPtr pObject, LPCTSTR szFormat);
	void ParseLineFormat( CPGLLinePtr pLine, LPCTSTR szFormat);
	void ParseErrorBarFormat(CPGLErrorBarPtr pError, LPCTSTR szFormat);
	void ParseScatterFormat(CPGLScatterPtr pError, LPCTSTR szFormat);
	void ParseImageFormat(CPGLImagePtr pImage, LPCTSTR szFormat);
	//@}

	//! Autoscale
	bool m_bAutoZoom;
	//! current dialog
	long m_dwCurDlgID;
	//! current region
	long m_dwCurRegionID;
	//! region container...
	RegionPtrContainer m_pRegions;
	//! GDIp interface
	gfxinterface::CGDIpInterface m_gdip;
	// list of dialogs
	boost::scoped_ptr<CPGLDialogList> m_lDialogs;
};

PGL_DECLARE_SMARTPTR( CPGLScript );

class CPGLScriptPoolSingleton;

/*! \name Script Table

  \ingroup ScriptGroup
*/
class PGLMFC_EXT_CLASS CPGLScriptPool
{
public:
	CPGLScriptPool();
	~CPGLScriptPool();
protected:
	friend class CPGLScriptPoolSingleton;

	typedef std::map< CString , CPGLScriptPtr > ScriptMap;

	void Clear();

	//! Creates a script engine
	void CreateScript(CString& str);
	
	//! Retreive script
	CPGLScriptPtr GetScript(LPCTSTR szScriptName);

	//! Remove script
	void RemoveScript( LPCTSTR szScriptName );
private:

	//! Script map
	ScriptMap m_scripts;
};

/*! \name Script table singleton

  \ingroup ScriptGroup
*/
class PGLMFC_EXT_CLASS CPGLScriptPoolSingleton : 
	public singletons::TSingleton< CPGLScriptPool , 5 >
{
public:
	//! Create a script object
	static void CreateScript(CString& str)					
	{	Instance()->CreateScript(str);};
	//! Return pointer to a script
	static CPGLScriptPtr GetScript(LPCTSTR szScriptName)		
	{	return Instance()->GetScript(szScriptName);};
	//! Remove script
	static void RemoveScript( LPCTSTR szScriptName )		
	{	Instance()->RemoveScript(szScriptName);};
};

#endif // !defined(AFX_PGLSCRIPT_H__701CD044_1B61_438F_B452_C688947E212C__INCLUDED_)
